`ifndef FIFO_MONITOR__SV
`define FIFO_MONITOR__SV

import uvm_pkg::*;
`include "uvm_macros.svh"
`include "fifo_transcation.sv"
class fifo_monitor extends uvm_monitor;
  `uvm_component_utils(fifo_monitor)
  
  function new(string name = "fifo_monitor",uvm_component parent = null);
    super.new(name,parent);
  endfunction
  
  virtual fifo_if vif;
  
  
  uvm_analysis_port#(fifo_transcation) ap;
  
  virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);
	`uvm_info("fifo_monitor","build_phase is called",UVM_LOW)
	if(!uvm_config_db#(virtual fifo_if)::get(this,"","vif",vif))
	  `uvm_fatal("fifo_monitor","vif must be set")
	
	
	ap = new("ap",this);
	
	
  endfunction
                    
  extern virtual task main_phase(uvm_phase phase);
  extern virtual task collect_one_pkt_in(fifo_transcation tr);
endclass

task fifo_monitor::main_phase(uvm_phase phase);

  fifo_transcation tr;
  `uvm_info("fifo_monitor","main_phase is called",UVM_LOW)
  //fifo_transcation tr;
  // old byte
  //-------------------------------------
  /* while(1)begin
	@(vif.init_done);
	while(vif.init_done) begin
	`uvm_info("fifo_monitor",$sformatf("monitor data : %d at %0t",vif.wr_data,$time),UVM_LOW)
    @(posedge vif.wrclk);
	#1;
	end
  end */
  //-------------------------------------
  
  // new byte
  repeat(100) begin
	tr = new("tr");
	collect_one_pkt_in(tr);
  end
//******** bug *****************////
// after finished repeat 
// not run uvm_info()    why??????  
//********************************//  
  `uvm_info("fifo_monitor","main phase is end",UVM_LOW) 
endtask

task fifo_monitor::collect_one_pkt_in(fifo_transcation tr);
	bit [15:0] data_q;
	  
	while(1) begin
		@(vif.init_done);
		while(vif.init_done) begin
		@(posedge vif.wrclk);
		#0.001;
		data_q = vif.wr_data;
		//`uvm_info("fifo_monitor_out",$sformatf("monitor data : %d at %0t",data_q,$time),UVM_LOW)
		tr.dmac = data_q;
		tr.my_print_mon_in();
		ap.write(tr);
		end
	end
	//`uvm_info("fifo_monitor_out","collect one pkt finished",UVM_LOW)
	//tr.dmac = data_q;
	//tr.my_print_mon_in();
endtask 

class fifo_monitor_out extends uvm_monitor;
  `uvm_component_utils(fifo_monitor_out)
  
  function new(string name = "fifo_monitor_out",uvm_component parent = null);
    super.new(name,parent);
  endfunction
  
  virtual fifo_if vif;
  
  virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);
	`uvm_info("fifo_monitor_out","build_phase is called",UVM_LOW)
	if(!uvm_config_db#(virtual fifo_if)::get(this,"","vif",vif))
	  `uvm_fatal("fifo_monitor_out","vif must be set")
  endfunction
                    
  extern virtual task main_phase(uvm_phase phase);
  extern virtual task collect_one_pkt_out(fifo_transcation tr);
endclass

task fifo_monitor_out::main_phase(uvm_phase phase);
  
  fifo_transcation tr;
  `uvm_info("fifo_monitor_out","main_phase is called",UVM_LOW)
  //old byte
  
  /*
  while(1)begin
	@(vif.init_done);
	while(vif.init_done) begin
	`uvm_info("fifo_monitor_out",$sformatf("monitor data : %d at %0t",vif.rd_data,$time),UVM_LOW)
    @(posedge vif.rdclk);
	#1;
	end
  end
  */
  
  //new byte

  repeat(100) begin
	tr = new("tr");
	collect_one_pkt_out(tr);
  end
  `uvm_info("fifo_monitor_out","main phase is end",UVM_LOW) 
endtask

task fifo_monitor_out::collect_one_pkt_out(fifo_transcation tr);
	bit [15:0] data_q;
	
	while(1) begin
		@(vif.init_done);
		while(vif.init_done) begin
		@(posedge vif.rdclk);
		#0.001;
		data_q = vif.rd_data;
		//`uvm_info("fifo_monitor_out",$sformatf("monitor data : %d at %0t",data_q,$time),UVM_LOW)
		//@(posedge vif.rdclk);
		//#1;
		tr.dmac = data_q;
		tr.my_print_mon_out();
		end
	end
	//`uvm_info("fifo_monitor_out","collect one pkt finished",UVM_LOW)
	//tr.dmac = data_q;
	//tr.my_print();
endtask
`endif
